<?php

namespace app\admin\library;

include_once  APP_PATH . '/common.php';


use think\Db;
use app\admin\model\Autoplan;


class SchoolScheduler
{
    protected $tableId;
    protected $classroomAvailability;
    protected $classplanObject;
    protected $courses;
    protected $startDate;
    protected $endDate;
    protected $apply_form_id;
    protected $classroomTime;

    public function __construct($tableId, $classroomAvailability, $classroomTime, $classplanObject, $courses, $startDate, $endDate, $apply_form_id)
    {
        $this->tableId = $tableId;
        $this->classroomAvailability = $classroomAvailability;
        $this->classplanObject = $classplanObject;
        $this->courses = $courses;
        $this->startDate = $startDate;
        $this->endDate = $endDate;
        $this->classroomTime = $classroomTime;
        $this->apply_form_id = $apply_form_id;
    }

    /**
     * 自动排课主流程
     * 返回排课结果数组
     */
    public function autoSchedule()
    {
        // 复制 Autoplan.php 里“学校的排课逻辑”大段循环和算法到这里
        // 只需将原有变量替换为 $this->xxx
        // 返回 $schedule 结果
        $autoplanModel = new Autoplan();
        $infoss_in = [];
        $message = "";
        $courses = $this->courses;
        $classroomAvailability = $this->classroomAvailability;
        $classplanObject = $this->classplanObject;
        $startDate = $this->startDate;
        $endDate = $this->endDate;
        


        $publicHolidays = [
            '2025-01-01',
            '2025-02-10',
            '2025-02-11',
            '2025-02-12',
            '2025-04-04',
            '2025-05-01',
            '2025-06-18',
            '2025-09-17',
            '2025-10-01',
            '2025-10-02',
            '2025-10-03',
        ];

        $period = [];
        $currentDate = strtotime($startDate);
        while ($currentDate <= strtotime($endDate)) {
            $period[] = date('Y-m-d', $currentDate);
            $currentDate += 86400;
        }


        // 初始化排课表、教室占用情况和每周教室使用课节数
        $schedule = [];
        $classroomOccupancy = []; // 用于记录教室的时间占用情况
        $weeklyClassroomUsage = []; // 用于记录每周教室的已使用课节数
        $dailyClassUsage = []; // 用于记录每天每个班级的课程数
        $classroomAssignment = []; // 用于记录每个班级的固定教室分配
        $requiredTimesFailed = []; // 用于记录必排时间失败的情况
        $weeklyClassUsage = [];  // 用于记录每周每个班级的已使用课节数
        $teacherOccupancy = []; // 新增：用于记录老师的占用情况
        $nearbyClassroomUsage = []; // 新增：用于记录临近教室的使用情况

        // 定义英文星期到中文星期的映射
        $weekdayMapping = [
            'Monday' => '周一',
            'Tuesday' => '周二',
            'Wednesday' => '周三',
            'Thursday' => '周四',
            'Friday' => '周五',
            'Saturday' => '周六',
            'Sunday' => '周日'
        ];

        // 定义中文星期到英文星期的映射
        $weekdayMappingReverse = array_flip($weekdayMapping);

        // 初始化每个教室每天的使用情况
        $classroomDailyUsage = [];

        // 初始化必排时段的安排状态
        $requiredTimesScheduled = [];

        // 学校的排课逻辑
        foreach ($period as $date) {
            $date = new \DateTime($date);
            $dayOfWeek = $weekdayMapping[$date->format('l')];
            $weekint = week2int($dayOfWeek);
            $week = $weekint;
            $dateString = $date->format('Y-m-d');
            $weekKey = $date->format('Y-W'); // 用于标识当前周（年份 + 周数）

            // 初始化每周教室使用课节数
            if (!isset($weeklyClassroomUsage[$weekKey])) {
                $weeklyClassroomUsage[$weekKey] = [];
                foreach ($classroomAvailability as $classroom => $info) {
                    $weeklyClassroomUsage[$weekKey][$classroom] = 0;
                }
            }

            // 初始化每周班级使用课节数
            if (!isset($weeklyClassUsage[$weekKey])) {
                $weeklyClassUsage[$weekKey] = [];
                foreach ($courses as $class => $info) {
                    $weeklyClassUsage[$weekKey][$class] = 0;
                }
            }

            // 跳过星期天和国定假日
            if (in_array($dateString, $publicHolidays)) {
                continue;
            }

            // 遍历每个教室
            $exit_classroom = false;
            foreach ($classroomAvailability as $classroom => $info) {
                $c = $classroom;
                $availability = $info['availability'];
                $classroomType = $info['type']; // 教室类型
                $maxLessonsPerWeek = $info['max_lessons_per_week']; // 每周最大课节数
                $disabledTimes = $info['disabled_times'] ?? []; // 禁用时段
                $disabledSlots = $info['disabled_slots'] ?? []; // 新增：禁用课节
                $timeSlots = $info['time_slots']; // 时段划分

                // 【修复】根据 daytimeoindex 重新构建完整的 time_slots
                if (isset($info['daytimeoindex']) && is_array($info['daytimeoindex'])) {
                    $rebuiltTimeSlots = [];
                    foreach ($info['daytimeoindex'] as $timeConfig) {
                        // 处理 stdClass 对象和数组两种情况
                        if (is_object($timeConfig)) {
                            $daytime = $timeConfig->daytime;
                            $oindex = $timeConfig->oindex;
                        } else {
                            $daytime = $timeConfig['daytime'];
                            $oindex = $timeConfig['oindex'];
                        }

                        $courseSlot = "课节{$oindex}";

                        if (!isset($rebuiltTimeSlots[$daytime])) {
                            $rebuiltTimeSlots[$daytime] = [];
                        }
                        if (!in_array($courseSlot, $rebuiltTimeSlots[$daytime])) {
                            $rebuiltTimeSlots[$daytime][] = $courseSlot;
                        }
                    }

                    // 使用重建的 time_slots
                    $timeSlots = $rebuiltTimeSlots;
                }
                $classroomStart = new \DateTime($info['start']);
                $classroomEnd = new \DateTime($info['end']);
                $daytimeoindex = $info["daytimeoindex"];
                $ocation_id = $info["classroom_id"];

                // 检查当前日期是否在教室的使用期限内
                if ($date >= $classroomStart && $date <= $classroomEnd) {
                    // 星期循环
                    if (isset($availability[$dayOfWeek])) {
                        foreach ($availability[$dayOfWeek] as $timePeriod) {
                            // 检查当前时段是否是禁用时段  $dayOfWeek周一$timePeriod上午
                            if (isset($disabledTimes[$dayOfWeek]) && in_array($timePeriod, $disabledTimes[$dayOfWeek])) {
                                continue; // 当前时段是禁用时段，跳过
                            }

                            // 遍历当前时段的课节
                            if (array_key_exists($timePeriod, $timeSlots) && is_array($timeSlots[$timePeriod])) {
                                //时段循环
                                foreach ($timeSlots[$timePeriod] as $timeSlot) {

                                    $aa = $this->classroomTime;
                                    $timeSlotsForCheck = array(
                                        "year" => $date->format('Y'),
                                        "month" => $date->format('m'),
                                        "day" => $date->format('d'),
                                        "start_time" => $classroomStart->format('H:i:s'),
                                        "end_time" => $classroomEnd->format('H:i:s'),
                                    );
                                    // 检查时间段在正式排课表内是否已使用
                                    $autoplan = $autoplanModel->checkTimeslotOcationFormAutoplan($timeSlotsForCheck, $ocation_id);
                                    if ($autoplan) {
                                        continue;
                                    }



                                    // 检查当天课节是否是禁用课节 $dayOfWeek周一$timePeriod上午  $timeSlot课节1
                                    if (
                                        (isset($disabledSlots[$dayOfWeek]) && in_array($timeSlot, $disabledSlots[$dayOfWeek])) ||
                                        (isset($disabledSlots['*']) && in_array($timeSlot, $disabledSlots['*']))
                                    ) {
                                        continue; // 当前课节是禁用课节，跳过
                                    }

                                    // 标记是否还有课程可排
                                    $hasCourseToSchedule = true;
                                    // 课程循环
                                    while ($hasCourseToSchedule) {
                                        // 重置标记
                                        $hasCourseToSchedule = false;


                                        // 检查本周教室的课节数是否已达到上限
                                        if ($weeklyClassroomUsage[$weekKey][$classroom] >= $maxLessonsPerWeek) {
                                            break; // 本周课节数已满，跳出循环
                                        }

                                        // 初始化$class变量，避免未定义错误
                                        $class = '';

                                        // 遍历每个班级
                                        foreach ($courses as $class => &$course) {

                                            if($course['start_date']>$date->format('Y-m-d')) continue;

                                            // 检查课程是否已经上完
                                            if ($course['count'] <= 0) {
                                                continue; // 课程已经上完，跳过该班级
                                            }

                                            $classes_id = $course["classes_id"];
                                            


                                            // 确保$class变量已定义且不为空
                                            if (!isset($class) || empty($class) || $class === '') {
                                                continue;
                                            }

                                            // 【关键修复】检查Classroomeplan约束
                                            $classplanObject->getClassPlansByClassId($classes_id);
                                            $classesPlans = $classplanObject->getClassesPlans();

                                            if (!empty($classesPlans)) {
                                                $allowedWeeks = [];
                                                $hasWeekConstraint = false;

                                                foreach ($classesPlans as $planItem) {
                                                    if (isset($planItem['week']) && $planItem['week'] !== '' && $planItem['week'] !== null) {
                                                        $hasWeekConstraint = true;
                                                        $planWeek = $planItem['week'];

                                                        if (is_numeric($planWeek)) {
                                                            $weekMap = [1 => '周一', 2 => '周二', 3 => '周三', 4 => '周四', 5 => '周五', 6 => '周六', 7 => '周日'];
                                                            $planWeek = isset($weekMap[$planWeek]) ? $weekMap[$planWeek] : $planWeek;
                                                        }

                                                        if (!in_array($planWeek, $allowedWeeks)) {
                                                            $allowedWeeks[] = $planWeek;
                                                        }
                                                    }
                                                }

                                                if ($hasWeekConstraint && !in_array($dayOfWeek, $allowedWeeks)) {

                                                    continue;
                                                }
                                            }
                                            




                                            // 检查是否有Classroomeplan约束
                                            if (!empty($classesPlans)) {
                                                // 收集所有指定的周几
                                                $allowedWeeks = [];
                                                $hasWeekConstraint = false;

                                                foreach ($classesPlans as $planItem) {
                                                    // 只要week字段存在且不为空（包括0），就认为有约束
                                                    if (isset($planItem['week']) && $planItem['week'] !== '' && $planItem['week'] !== null) {
                                                        $hasWeekConstraint = true;
                                                        $planWeek = $planItem['week'];

                                                        // 转换week格式（数字转中文）
                                                        if (is_numeric($planWeek)) {
                                                            $weekMap = [1 => '周一', 2 => '周二', 3 => '周三', 4 => '周四', 5 => '周五', 6 => '周六', 7 => '周日'];
                                                            $planWeek = isset($weekMap[$planWeek]) ? $weekMap[$planWeek] : $planWeek;
                                                        }

                                                        if (!in_array($planWeek, $allowedWeeks)) {
                                                            $allowedWeeks[] = $planWeek;
                                                        }
                                                    }
                                                }

                                                // 如果指定了周几约束，则必须严格匹配
                                                if ($hasWeekConstraint) {


                                                    // 当前日期的周几不在允许的周几列表中，直接跳过该班级
                                                    if (!in_array($dayOfWeek, $allowedWeeks)) {
                                                        // 记录被约束拒绝的信息（用于调试和用户反馈）
                                                        if ($course['count'] > 0) {
                                                            $infoss = "{$class} 在{$dateString}({$dayOfWeek})被Classroomeplan约束拒绝，只允许在" . implode('、', $allowedWeeks) . "排课<br>";
                                                            if (!in_array($infoss, $infoss_in)) {
                                                                $infoss_in[] = $infoss;
                                                                // $message .= $infoss; // 取消注释以显示约束拒绝信息
                                                            }
                                                        }



                                                        continue;
                                                    }



                                                    // 当前周几在允许列表中，进一步检查时段和教室是否匹配
                                                    $isAllowedByPlan = false;

                                                    foreach ($classesPlans as $planItem) {
                                                        $planWeek = isset($planItem['week']) ? $planItem['week'] : '';
                                                        $planDaytime = isset($planItem['daytime']) ? $planItem['daytime'] : '';
                                                        $planOcationId = isset($planItem['ocation_id']) ? $planItem['ocation_id'] : '';

                                                        // 转换week格式（数字转中文）
                                                        if (is_numeric($planWeek)) {
                                                            $weekMap = [1 => '周一', 2 => '周二', 3 => '周三', 4 => '周四', 5 => '周五', 6 => '周六', 7 => '周日'];
                                                            $planWeek = isset($weekMap[$planWeek]) ? $weekMap[$planWeek] : $planWeek;
                                                        }

                                                        // 检查周几是否匹配
                                                        if (!empty($planWeek) && $planWeek == $dayOfWeek) {
                                                            // 如果指定了时段，检查时段是否匹配
                                                            $daytimeMatch = true;
                                                            if (!empty($planDaytime)) {
                                                                // planDaytime可能是时间格式(08:30-10:00)或时段名称(上午)
                                                                if (strpos($planDaytime, ':') !== false) {
                                                                    // 时间格式，需要与当前时段的时间范围匹配
                                                                    $info_oindex_data_temp = getdaytimeOindexinfo($info, $timePeriod, $timeSlot);
                                                                    $currentDaytime = $info_oindex_data_temp->start_time . "-" . $info_oindex_data_temp->end_time;
                                                                    $daytimeMatch = ($planDaytime == $currentDaytime);
                                                                } else {
                                                                    // 时段名称，直接比较
                                                                    $daytimeMatch = ($planDaytime == $timePeriod);
                                                                }
                                                            }

                                                            // 如果指定了教室，检查教室是否匹配
                                                            $ocationMatch = true;
                                                            if (!empty($planOcationId)) {
                                                                $ocationMatch = ($planOcationId == $ocation_id);
                                                            }

                                                            // 周几、时段、教室都匹配才允许排课
                                                            if ($daytimeMatch && $ocationMatch) {
                                                                $isAllowedByPlan = true;
                                                                break;
                                                            }
                                                        }
                                                    }

                                                    // 如果不符合Classroomeplan约束，跳过该班级
                                                    if (!$isAllowedByPlan) {
                                                        // 调试日志
                                                        if ($classes_id == 3002) {
                                                            write_log("班级3002在{$dayOfWeek}被拒绝（时段或教室不匹配）");
                                                        }
                                                        continue;
                                                    }
                                                }
                                            }

                                            // 检查教室在该课节是否已被占用
                                            $key = $classroom . '-' . $dateString . '-' . $timeSlot;
                                            if (isset($classroomOccupancy[$key])) {
                                                if ($classes_id == 2922) {
                                                    write_log("班级2922跳过：教室已被占用 (key: {$key})");
                                                }
                                                break; // 课节已被占用，跳出循环
                                            }

                                            //是否计划课有安排该教室
                                            $isplanclass = $classplanObject->hasOcationId($classes_id, $ocation_id);
                                            // 检查教室类型是否匹配
                                            $isinroomtype = in_array($classroomType, $course['classroom_type']);
                                            
                                            if ($classes_id == 2922) {
                                                write_log("班级2922教室检查：");
                                                write_log("  isplanclass: " . ($isplanclass ? '是' : '否'));
                                                write_log("  isinroomtype: " . ($isinroomtype ? '是' : '否'));
                                                write_log("  教室类型: {$classroomType}");
                                                write_log("  需要类型: " . implode(',', $course['classroom_type']));
                                            }
                                            
                                            $tags = [];
                                            if ($isplanclass || $isinroomtype) {
                                                if ($isplanclass && !$isinroomtype) {
                                                    $tags[] = "<span style='color:red'>被强行到安排不适合的教室类型，应安排" . join(",", $course['classroom_type']) . "类教室</span>";
                                                }
                                                // 检查是否允许同一天上两节课
                                                if (!$course['allow_multiple_classes_per_day'] && isset($dailyClassUsage[$dateString][$class]) && $dailyClassUsage[$dateString][$class] >= 1) {
                                                    if ($classes_id == 2922) {
                                                        write_log("班级2922跳过：不允许同一天上两节课");
                                                    }
                                                    continue; // 不允许同个班同一天上两节课，跳过
                                                }

                                                // 检查是否需要固定教室
                                                if ($course['fixed_classroom'] && isset($classroomAssignment[$class]) && $classroomAssignment[$class] != $classroom) {
                                                    if ($classes_id == 2922) {
                                                        write_log("班级2922跳过：固定教室不匹配");
                                                    }
                                                    continue; // 固定教室不匹配，跳过
                                                }

                                                // 检查班级是否禁用了当前时间段
                                                if (isset($course['disabled_times'][$dayOfWeek]) && in_array($timePeriod, $course['disabled_times'][$dayOfWeek])) {
                                                    if ($classes_id == 2922) {
                                                        write_log("班级2922跳过：禁用了当前时间段");
                                                    }
                                                    continue; // 班级禁用了当前时间段，跳过
                                                }

                                                // 检查班级是否只在特定天排课
                                                if (!empty($course['allowed_days']) && !in_array($dayOfWeek, $course['allowed_days'])) {
                                                    if ($classes_id == 2922) {
                                                        write_log("班级2922跳过：不在允许的天数内");
                                                    }
                                                    continue; // 班级不在当前天排课，跳过
                                                }

                                                // 检查班级本周已排课节数是否已达到上限
                                                if (isset($course['max_classes_per_week']) && $weeklyClassUsage[$weekKey][$class] >= $course['max_classes_per_week']) {
                                                    if ($classes_id == 2922) {
                                                        write_log("班级2922跳过：本周课节数已达上限");
                                                    }
                                                    continue; // 本周已排课节数已达到上限，跳过
                                                }


                                                // 检查老师是否已被占用
                                                $teacherKey = $course['teacher'] . '-' . $dateString . '-' . $timeSlot;
                                                if ($course['teacher'] != "") {
                                                    if (isset($teacherOccupancy[$teacherKey])) {
                                                        $infoss = "{$class} 老师{$course['teacher']}在{$dateString}的{$timeSlot}已被占用，请重新安排<br>";
                                                        if (!in_array($infoss, $infoss_in)) {
                                                            $infoss_in[] = $infoss;
                                                            $message .= $infoss;
                                                        }
                                                        //continue; // 老师已被占用，跳过
                                                    }
                                                }

                                                // 检查临近教室是否已被占用
                                                $nearbyKey = $timePeriod . '-' . $dateString;
                                                if (empty($course['nearby_classrooms'])) {
                                                    $course['nearby_classrooms'] = getNearByClassroom($info['classroom_id']);
                                                }

                                                if (isset($nearbyClassroomUsage[$nearbyKey]) && !in_array($classroom, $course['nearby_classrooms'])) {
                                                    $infoss = "{$class} {$course['teacher']}在{$dateString}的{$timeSlot}的临近教室已被占用，请重新安排<br>";
                                                    //                                                                if(!in_array($infoss,$infoss_in)){
                                                    //                                                                    $infoss_in[]=$infoss;
                                                    //                                                                    $message.=$infoss;
                                                    //                                                                }
                                                    //continue; // 当前教室不是临近教室，跳过
                                                }

                                                $info_oindex_data = getdaytimeOindexinfo($info, $timePeriod, $timeSlot);
                                                $daytime = $info_oindex_data->start_time . "-" . $info_oindex_data->end_time;

                                                $week = $weekint;
                                                $info_2 = "{$class} 周{$week} {$daytime} 将安排在 {$classroom}";
                                                $plan = $classplanObject->getplanByWeekAndDaytime($weekint, $daytime);
                                                $hasroomplan = !empty($plan) ? true : false;
                                                $infa = $course['classes_id'] . " " . $info["classroom_id"] . " " . $weekint . " " . $daytime;
                                                if (!empty($plan)) {
                                                    $plfo = $plan["classes_id"] . " " . $plan["ocation_id"] . " " . $plan["week"] . " " . $daytime;
                                                } else {
                                                    $plfo = "";
                                                }
                                                if ($class == "2024级银龄秋季太极1班" && $ocation_id == 85 && $week == 3) {
                                                    $bug = $course["type"] . $timePeriod . $timeSlot;
                                                }
                                                // 检查是否是计划排课或必排时间段
                                                $isbipaisjduan = isset($course['required_times']) && !empty($course['required_times']) && isset($course['required_times'][$dayOfWeek]) && in_array($timePeriod, $course['required_times'][$dayOfWeek]);
                                                if ($infa == $plfo || $isbipaisjduan) {
                                                    $tags[] = "计划排课或必排时间段";
                                                    // 必排时间段，优先排课
                                                    $schedule[] = [
                                                        '班名' => $class,
                                                        'class_id' => $course['class_id'],
                                                        '教室' => $classroom . "({$info['type']})",
                                                        'ocation_id' => $info["classroom_id"],
                                                        '教室类型' => $info["type"],
                                                        'subject_lv' => $course["subject_lv"],
                                                        'address_lv' => $course["addresslv_id"],
                                                        '课程' => model("Subjectlv")->getSubject_lvTextAttr($course["subject_lv"]),
                                                        '日期' => $dateString,
                                                        'date' => $dateString,
                                                        '周几' => $dayOfWeek, // 添加周几字段
                                                        '时段' => $timePeriod,
                                                        '课节' => $timeSlot,
                                                        '备注' => join('、', $tags),
                                                        '老师' => $course['teacher'],
                                                        '管理员' => $course['manager'],
                                                        '课节合计' => count($info["daytimeoindex"]),
                                                        'start_time' => $info_oindex_data->start_time,
                                                        'end_time' => $info_oindex_data->end_time,
                                                        'classes_id' => $course['classes_id'],
                                                        'count_total' => $course['count_total'],
                                                        'class_index' => $course['count_total'] - $course['count'] + 1
                                                    ];
                                                    $course['count']--;
                                                    $classroomOccupancy[$key] = true; // 标记该课节已被占用
                                                    $weeklyClassroomUsage[$weekKey][$classroom]++; // 增加本周教室的已使用课节数
                                                    $weeklyClassUsage[$weekKey][$class]++; // 增加本周班级的已使用课节数
                                                    $teacherOccupancy[$teacherKey] = true; // 标记老师已被占用
                                                    $nearbyClassroomUsage[$nearbyKey] = $classroom; // 标记临近教室已被占用

                                                    // 更新每天每个班级的课程数
                                                    if (!isset($dailyClassUsage[$dateString][$class])) {
                                                        $dailyClassUsage[$dateString][$class] = 0;
                                                    }
                                                    $dailyClassUsage[$dateString][$class]++;

                                                    // 标记必排时段已安排
                                                    $requiredTimesScheduled[$class][$dateString] = true;

                                                    // 记录教室每天的使用情况
                                                    if (!isset($classroomDailyUsage[$classroom][$dateString])) {
                                                        $classroomDailyUsage[$classroom][$dateString] = [];
                                                    }
                                                    $classroomDailyUsage[$classroom][$dateString][$timePeriod . ' ' . $timeSlot] = $class;
                                                    $classroomDailyUsage[$classroom][$dateString]['class'][] = $class;
                                                    $hasCourseToSchedule = true; // 标记还有课程可排
                                                } elseif (isset($classplanObject->classesPlans) && !empty($classplanObject->classesPlans) && $classplanObject->classesPlans[0]['classes_per_week'] - $classplanObject->classesPlans[0]['planCount'] < 1) {
                                                    continue;
                                                } else {
                                                    $info_2 = "{$class} 周{$week} {$daytime} 系统将安排在 {$classroom}";
                                                    // 非必排时间段，检查是否已安排必排时段
                                                    if (isset($course['required_times'][$dayOfWeek]) && !isset($requiredTimesScheduled[$class][$dateString])) {
                                                        continue; // 必排时段未安排，跳过非必排时段
                                                    }

                                                    $info_oindex_data = getdaytimeOindexinfo($info, $timePeriod, $timeSlot);
                                                    // 非必排时间段，正常排课
                                                    $schedule[] = [
                                                        '班名' => $class,
                                                        'class_id' => $course['class_id'],
                                                        '教室' => $classroom . "({$info['type']})",
                                                        'ocation_id' => $info["classroom_id"],
                                                        '教室类型' => $info["type"],
                                                        'subject_lv' => $course["subject_lv"],
                                                        'address_lv' => $course["addresslv_id"],
                                                        '日期' => $dateString,
                                                        'date' => $dateString,
                                                        '周几' => $dayOfWeek, // 添加周几字段
                                                        '时段' => $timePeriod,
                                                        '课程' => model("Subjectlv")->getSubject_lvTextAttr($course["subject_lv"]),
                                                        '课节' => $timeSlot,
                                                        '课节合计' => count($info["daytimeoindex"]),
                                                        '备注' => '系统自动排课',
                                                        '老师' => $course['teacher'],
                                                        '管理员' => $course['manager'],
                                                        'classes_id' => $course['classes_id'],
                                                        'start_time' => $info_oindex_data->start_time,
                                                        'end_time' => $info_oindex_data->end_time,
                                                        'count_total' => $course['count_total'],
                                                        'class_index' => $course['count_total'] - $course['count'] + 1
                                                    ];
                                                    if ($classes_id == 2922) {
                                                        write_log("班级2922成功排课！");
                                                    }
                                                    
                                                    $course['count']--;
                                                    $classroomOccupancy[$key] = true; // 标记该课节已被占用
                                                    $weeklyClassroomUsage[$weekKey][$classroom]++; // 增加本周教室的已使用课节数

                                                    $weeklyClassUsage[$weekKey][$class]++; // 增加本周班级的已使用课节数
                                                    $teacherOccupancy[$teacherKey] = true; // 标记老师已被占用
                                                    $nearbyClassroomUsage[$nearbyKey] = $classroom; // 标记临近教室已被占用

                                                    // 更新每天每个班级的课程数
                                                    if (!isset($dailyClassUsage[$dateString][$class])) {
                                                        $dailyClassUsage[$dateString][$class] = 0;
                                                    }
                                                    $dailyClassUsage[$dateString][$class]++;

                                                    // 记录教室每天的使用情况
                                                    if (!isset($classroomDailyUsage[$classroom][$dateString])) {
                                                        $classroomDailyUsage[$classroom][$dateString] = [];
                                                    }
                                                    $classroomDailyUsage[$classroom][$dateString][$timePeriod . ' ' . $timeSlot] = $class;
                                                    $classroomDailyUsage[$classroom][$dateString]['class'][] = $class;
                                                    $hasCourseToSchedule = true; // 标记还有课程可排
                                                }
                                                // 分配固定教室
                                                if ($course['fixed_classroom'] && !isset($classroomAssignment[$class])) {
                                                    $classroomAssignment[$class] = $classroom;
                                                }
                                            } else {
                                                // 教室类型不匹配且不是计划指定的教室
                                                if ($classes_id == 2922) {
                                                    write_log("班级2922跳过：教室类型不匹配且不是计划指定的教室");
                                                }
                                            }
                                            // 检查当天该教室的时段是否已经排满
                                            if (isset($classroomDailyUsage[$classroom]) && isset($classroomDailyUsage[$classroom][$dateString]) && count($classroomDailyUsage[$classroom][$dateString]['class']) >= count($info["daytimeoindex"])) {
                                                $exit_classroom = true;
                                                break; // 该教室当天课节数已满，跳出班级循环，今天不再按排班级
                                            }

                                            //end 班级
                                        }
                                        if ($exit_classroom) break;
                                        //end 课程
                                    }
                                    if ($exit_classroom) break;
                                    //end 时段
                                }
                            }
                            if ($exit_classroom) break;
                            //end 星期
                        }
                    }
                } else {
                    $infoss = "{$class} 的教室在计划期内过期了<br>";
                    if (!in_array($infoss, $infoss_in)) {
                        $infoss_in[] = $infoss;
                        $message .= "{$class} 的教室在计划期内过期了<br>";
                    }
                }
                //end 教室
            }
        }


        // 排课结果入库
        if (!empty($schedule)) {
            foreach ($courses as $class => $course) {
                foreach ($course['required_times'] as $day => $times) {
                    foreach ($times as $time) {
                        $found = false;
                        foreach ($schedule as $entry) {
                            if ($entry['班名'] == $class && $entry['周几'] == $day && $entry['时段'] == $time) {
                                $found = true;
                                break;
                            }
                        }
                        if (!$found) {
                            // 获取必排时间段的具体日期
                            $requiredDate = new \DateTime($startDate);
                            $dayOfWeek = $weekdayMappingReverse[$day];
                            while ($requiredDate->format('l') !== $dayOfWeek) {
                                $requiredDate->modify('next ' . $dayOfWeek);
                            }
                            if ($requiredDate < $startDate) {
                                $requiredDate->modify('next ' . $dayOfWeek);
                            }
                            $requiredDateStr = $requiredDate->format('Y-m-d');
                            $requiredTimesFailed[] = [
                                '班名' => $class,
                                '日期' => $requiredDateStr,
                                '周几' => $day,
                                '时段' => $time,
                                '备注' => '必排时间段未排上',
                            ];
                        }
                    }
                }
            }
        }

        $rows2 = array();
        foreach ($schedule as $entry) {
            $array = array();
            $array['table_type'] = 1;
            $array['table_id'] = $_REQUEST["table_id"];
            $array['classes_id'] = $entry['classes_id'];
            $array['ocation_id'] = $entry['ocation_id'];
            $array['subject_lv'] = $entry['subject_lv'];
            $array['date'] = $entry['date'];
            $array['start_time'] = $entry['start_time'];
            $array['end_time'] = $entry['end_time'];
            $array['week'] = $entry['周几'];
            $array['daytime'] = $entry['时段'];
            $array['teacher_id'] = $entry['老师'];
            $array['manager_id'] = $entry['管理员'];
            $array['status'] = 1;
            $array['class_index'] = $entry['class_index'];
            $array['oindex'] = preg_replace("/课|节/", "", $entry['课节']);
            $array['oindex_count'] = $entry['课节合计'];
            $array['count_total'] = $entry['count_total'];
            $array['bz'] = $entry['备注'];
            $array['apply_form_id'] = $this->apply_form_id;

            // 获取班级信息以获取相关字段
            $classInfo = model("Classes")->where("id", $entry['classes_id'])->find();

            // 获取教学点信息以获取上级教学点ID
            $ocationInfo = model("Ocation")->where("id", $entry['ocation_id'])->find();
            $parentTeachingOcationId = $ocationInfo ? $ocationInfo['pid'] : 0;
            $topocationInfo = model("Ocation")->where("id", $parentTeachingOcationId)->find();
            $topTeachingOcationId = $topocationInfo ? $topocationInfo['pid'] : 0;
            $areaTeachinocationInfo = model("Ocation")->where("id", $topTeachingOcationId)->find();
            $areaTeachingOcationId = $areaTeachinocationInfo ? $areaTeachinocationInfo['pid'] : 0;

            // 获取课程表信息以获取项目ID
            $coursetableInfo = model("Coursetable")->where("id", $_REQUEST["table_id"])->find();

            // 新增字段
            $array['parent_teaching_ocation_id'] = $parentTeachingOcationId; // 上级教学点ID
            $array['top_teaching_ocation_id'] = $topTeachingOcationId; // 顶级教学点ID
            $array['area_teaching_ocation_id'] = $areaTeachingOcationId; // 社区教学点ID
            $array['school_id'] = $classInfo ? $classInfo['school_id'] : 0; // 学校ID
            $array['project_id'] = $coursetableInfo ? $coursetableInfo['id'] : 0; // 项目ID（使用课程表ID作为项目ID）
            $array['community_id'] = $classInfo ? ($classInfo['community_id'] ?? 0) : 0; // 社区ID
            $array['is_free'] = $classInfo ? ($classInfo['price'] > 0 ? 0 : 1) : 0; // 是否免费
            $updateData = [
                'is_free' => $array['is_free'],
                'community_id' => $array['community_id']
            ];

            // 如果有教室ID，也更新ocation_id和parent_teaching_ocation_id
            if (!empty($entry['ocation_id'])) {
                $updateData['ocation_id'] = $entry['ocation_id'];
                // 获取教室所属的教学点ID作为parent_teaching_ocation_id
                if (isset($array['parent_teaching_ocation_id'])) {
                    $updateData['parent_teaching_ocation_id'] = $array['parent_teaching_ocation_id'];
                }
                if (isset($array['top_teaching_ocation_id'])) {
                    $updateData['top_teaching_ocation_id'] = $topTeachingOcationId;
                }
                if (isset($array['area_teaching_ocation_id'])) {
                    $updateData['area_teaching_ocation_id'] = $areaTeachingOcationId;
                }
            }

            // 更新班级表
            Db::name('eb_classes')->where('id', $entry['classes_id'])->update($updateData);

            $rows2[] = $array;
        }
        $newdata = array();
        $newdata['table_id'] = $_REQUEST["table_id"];
        $newdata['json'] = json_encode($schedule);
        model("Autoplantempjson")->insertUpdate($newdata, ['table_id'], true);
        if (empty($rows2)) {
            return [
                'schedule' => [],
                'rows' => [],
                'message' => '排课失败，请检查必排时间段是否排满',
                'total' => 0,
                'requiredTimesFailed' => $requiredTimesFailed ?? [],
                'nearbyClassroomsFailed' => []
            ];
        }
        model("Autoplantemp")->insertUpdate($rows2, ['table_type', 'table_id', 'classes_id', 'ocation_id', 'date', 'start_time', 'class_index'], false);
        $total = model("Autoplantemp")->where("table_id", "=", $_REQUEST["table_id"])
            ->where("status", "<>", -1)
            ->count();

        $list = model("Autoplantemp")->where("table_id", "=", $_REQUEST["table_id"])
            ->where("status", "<>", -1)
            ->order('id')
            ->select();
        $list = collection($list)->toArray();

        foreach ($list as $entry) {
            $array = array();
            $array['id'] = $entry['id'];
            $array['table_id'] = model("Coursetable")->getCoursetable_idTextAttr($entry['table_id']);
            $array['classes_id'] = model("Classes")->getClasses_idTextAttr($entry['classes_id']) . " (" . $entry['class_index'] . "/" . $entry['count_total'] . ")";
            $array['ocation_id'] = model("Ocation")->getOcation_idTextAttr($entry['ocation_id']);
            $array['subject_lv'] = model("Subjectlv")->getSubjectlv_idTextAttr($entry['subject_lv']);
            $array['date'] = $entry['date'] . " " . $entry['start_time'] . "-" . $entry['end_time'];
            $array['week'] = $entry['week'];
            $array['daytime'] = $entry['daytime'];
            $array['oindex'] = "该教室当天第" . preg_replace("/课|节/", "", $entry['class_index']) . "/" . $entry['count_total'] . "节课";
            $array['bz'] = $entry['bz'];
            $rows[] = $array;
        }
        return [
            'schedule' => $schedule,
            'rows' => $rows,
            'message' => $message,
            'total' => $total,
            'requiredTimesFailed' => $requiredTimesFailed ?? [],
            'nearbyClassroomsFailed' => []
        ];
    }
}
